using System.Linq.Expressions;
using Ellwood.Manage.Common.Core.result;
using SqlSugar;

namespace Ellwood.Manage.Common.Core.Basis.Service;

/// <summary>
/// Service基础类接口实现
/// </summary>
public abstract class BaseServiceImpl:IBaseService
{

    /// <summary>
    /// 链接数据库操作专用的SqlSugar
    /// </summary>
    private ISqlSugarClient _client { get; set; }

    public BaseServiceImpl(ISqlSugarClient client)
    {
        _client = client;
    }
    
    #region 基础方法--查询Query

    /// <summary>
    /// 主键查询
    /// </summary>
    /// <param name="id"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T Find<T>(int id) where T : class
    {
        return _client.Queryable<T>().InSingle(id);
    }

    /// <summary>
    /// 主键查询--异步版本
    /// </summary>
    /// <param name="id"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<T> FindAsync<T>(int id) where T : class
    {
        return await _client.Queryable<T>().InSingleAsync(id);
    }

    /// <summary>
    /// 不应该暴露给上端使用者，尽量少用
    /// 提供对表单的查询
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns>ISugarQueryable类型集合</returns>
    [Obsolete("尽量避免使用，using带表达式的目录树的 代替")]
    public ISugarQueryable<T> Set<T>() where T : class
    {
        return _client.Queryable<T>();
    }

    /// <summary>
    /// 条件查询
    /// </summary>
    /// <param name="funcWhere"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public ISugarQueryable<T> Query<T>(Expression<Func<T, bool>> funcWhere) where T : class
    {
        return _client.Queryable<T>().Where(funcWhere);
    }

    /// <summary>
    /// 分页查询
    /// </summary>
    /// <param name="funcWhere"></param>
    /// <param name="pageSize"></param>
    /// <param name="pageIndex"></param>
    /// <param name="funcOrderBy"></param>
    /// <param name="isAsc"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public PagingData<T> QueryPage<T>(Expression<Func<T, bool>> funcWhere, int pageSize, int pageIndex,
        Expression<Func<T, object>> funcOrderBy, bool isAsc = true) where T : class
    {
        var list = _client.Queryable<T>();
        if (funcWhere != null)
        {
            list = list.Where(funcWhere);
        }
        list = list.OrderByIF(true, funcOrderBy, isAsc ? OrderByType.Asc : OrderByType.Desc);
        PagingData<T> result = new PagingData<T>()
        {
            DataList = list.ToPageList(pageIndex, pageSize),
            PageIndex = pageIndex,
            PageSize = pageSize,
            RecordCount = list.Count()
        };
        return result;
    }

    #endregion

    #region 基础方法--新增Add

    /// <summary>
    /// 新增数据-同步版本
    /// </summary>
    /// <param name="t"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T Insert<T>(T t) where T : class, new()
    {
        return _client.Insertable<T>(t).ExecuteReturnEntity();
    }

    /// <summary>
    /// 新增数据-异步版本
    /// </summary>
    /// <param name="t"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<T> InsertAsync<T>(T t) where T : class, new()
    {
        return await _client.Insertable<T>(t).ExecuteReturnEntityAsync();
    }

    /// <summary>
    ///  批量新增-事务执行
    /// </summary>
    /// <param name="tList"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<bool> InsertList<T>(List<T> tList) where T : class, new()
    {
        return await _client.Insertable<T>(tList.ToList()).ExecuteCommandIdentityIntoEntityAsync();
    }

    #endregion

    #region 基础方法--更新Update

    /// <summary>
    /// 更新数据，即时Commit
    /// </summary>
    /// <param name="t"></param>
    /// <typeparam name="T"></typeparam>
    public void Update<T>(T t) where T : class, new()
    {
        if (t==null)
        {
            throw new Exception("传入参数不能为空");
        }

        _client.Updateable(t).ExecuteCommand();
    }

    /// <summary>
    /// 更新数据--异步版本，即时Commit
    /// </summary>
    /// <param name="t"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task UpdateAsync<T>(T t) where T : class, new()
    {
        if (t==null)
        {
            throw new Exception("传入参数不能为空");
        }

        await _client.Updateable(t).ExecuteCommandAsync();
    }

    /// <summary>
    /// 更新数据，即时Commit
    /// </summary>
    /// <param name="tList"></param>
    /// <typeparam name="T"></typeparam>
    public void Update<T>(List<T> tList) where T : class, new()
    {
        _client.Updateable(tList).ExecuteCommand();
    }

    #endregion

    #region 基础方法--删除Delete

    /// <summary>
    /// 根据主键删除数据
    /// </summary>
    /// <param name="pId"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public bool Delete<T>(object pId) where T : class, new()
    {
        T t = _client.Queryable<T>().InSingle(pId);
        return _client.Deleteable(t).ExecuteCommandHasChange();
    }

    /// <summary>
    /// 根据主键删除数据--异步版本
    /// </summary>
    /// <param name="pId"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public async Task<bool> DeleteAsync<T>(object pId) where T : class, new()
    {
        T t = _client.Queryable<T>().InSingle(pId);
        return await _client.Deleteable(t).ExecuteCommandHasChangeAsync();
    }

    /// <summary>
    /// 删除数据，即时Commit
    /// </summary>
    /// <param name="t"></param>
    /// <typeparam name="T"></typeparam>
    public void Delete<T>(T t) where T : class, new()
    {
        _client.Deleteable(t).ExecuteCommand();
    }

    /// <summary>
    /// 根据集合删除数据，即时Commit
    /// </summary>
    /// <param name="tListt"></param>
    /// <typeparam name="T"></typeparam>
    public void Delete<T>(List<T> tListt) where T : class, new()
    {
        _client.Deleteable(tListt).ExecuteCommand();
    }

    #endregion

    #region 基础方法--Other

    /// <summary>
    /// 执行sql,返回集合
    /// </summary>
    /// <param name="sql"></param>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    ISugarQueryable<T> IBaseService.ExcuteQuery<T>(string sql) where T : class
    {
        return _client.SqlQueryable<T>(sql);
    }

    public void Dispose()
    {
        if (_client!=null)
        {
            _client.Dispose();
        }
    }

    #endregion
}